/**
 * Project: Utilities <br>
 * Package: org.leumasjaffe.util
 */
package org.leumasjaffe.builder;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

import org.eclipse.jdt.annotation.NonNullByDefault;

/**
 * Class org.leumasjaffe.util..ConstructorBuilder in file ConstructorBuilder.java <br>
 * 
 * @author leumasjaffe
 * @version Jun 7, 2013
 * Created on: Jun 7, 2013
 * 
 */
@NonNullByDefault
public class ConstructorBuilder<T> extends DelegateBuilder<T> implements Builder<T> {
	
	private final Constructor<? extends T> constr;
	private final Class<?>[] paramTypes;
	
	/**
	 * @param constr
	 */
	@SuppressWarnings("null")
	public ConstructorBuilder(Constructor<? extends T> constr) {
		super(constr.getParameterTypes().length);
		this.constr = constr;
		this.paramTypes = constr.getParameterTypes();
	}
	
	/**
	 * @param paramNumber
	 * @param arg
	 */
	private void validateParameter(int paramNumber, Object arg) {
		if (this.paramTypes[paramNumber].isInstance(arg)) {
			throw new IllegalArgumentException("Parameter for argument #" + paramNumber + 
					"is of incompatible type: Expected " + 
					this.paramTypes[paramNumber].getSimpleName() + " but got " +
					arg.getClass().getSimpleName());
		}
	}
	
	/* (non-Javadoc)
	 * @see org.leumasjaffe.builder.DelegateBuilder#set(int, java.lang.Object)
	 */
	@Override
	public Builder<T> set(int paramNumber, Object arg) {
		validateParameter(paramNumber, arg);
		return super.set(paramNumber, arg);
	}
	
	@SuppressWarnings("null")
	@Override
	protected T __build() {
		try {
			return this.constr.newInstance(this.contents);
		} catch (InstantiationException | IllegalAccessException
				| IllegalArgumentException | InvocationTargetException e) {
			throw new AssertionError("Count not construct object: " + e.getLocalizedMessage());
		}
	}

}
